from .relation import Connected


class WuXing:
    """
    五行：只使用get_item返回指定的对象
    """
    _cache = {}
    _inited = False

    def __new__(cls, name, no, alias):
        if cls._inited:
            raise RuntimeError(f'{cls.__name__} 已经加载，不能直接实例化，请使用 {cls.__name__}.get_item(name)')
        if name in cls._cache:
            return cls._cache[name]
        else:
            self = super().__new__(cls)
            cls._cache[name] = self
            return self

    def __init__(self, name, no, alias):
        self.name = name
        self.no = no  # 编号
        self.alias = alias

    @classmethod
    def init_wuxing(cls, items):
        """
        初始化的时候调用一次
        """
        for name, no, alias in items:
            cls(name, no, alias)
        cls._inited = True

    @classmethod
    def get_item(cls, name):
        """
        返回指定的对象
        """
        return cls._cache[name]

    def distance(self, other):
        """
        环五行距离
        """
        return (other.no - self.no) % 5

    @classmethod
    def get_sheng_ke(cls, this, that):
        """
        计算self和other的生克关系
        """
        if this.wuxing.sheng(that.wuxing): return WuXingShengKe(this.name, that.name, '生')
        elif this.wuxing.bei_sheng(that.wuxing): return WuXingShengKe(that.name, this.name, '生')
        elif this.wuxing.ke(that.wuxing): return WuXingShengKe(this.name, that.name, '克')
        elif this.wuxing.bei_ke(that.wuxing): return WuXingShengKe(that.name, this.name, '克')
        else: return WuXingShengKe(this.name, that.name, '比和')

    def sheng(self, other):
        """self生other"""
        return self.distance(other) == 1

    def ke(self, other):
        """self克other"""
        return self.distance(other) == 2

    def bei_ke(self, other):
        """self被other克"""
        return self.distance(other) == 3

    def bei_sheng(self, other):
        """self被other生"""
        return self.distance(other) == 4

    def same_as(self, other):
        """self与other同五行"""
        return self.distance(other) == 0

    def __str__(self):
        return self.name

    @classmethod
    def calc_zhu_shengke(cls, mingpan):
        sizhu = mingpan.sizhu
        ans = []
        # 单注的生克关系
        for zhu in sizhu:
            tg_cell, dz_cell = zhu[0], zhu[1]  # cell
            ans.append(Connected(
                cls.get_sheng_ke(tg_cell.gan, dz_cell.zhi),
                mingpan,
                [tg_cell, dz_cell])
            )
        return ans

    @classmethod
    def calc_gan_shengke(cls, mingpan):
        sizhu = mingpan.sizhu
        ans = []
        for i in range(3):
            # 与右边一项检查(相邻)
            # 相邻两天干之间的生克关系
            tg_cell1, tg_cell2 = sizhu[i][0], sizhu[i+1][0]
            if tg_cell1.gan.wuxing != tg_cell2.gan.wuxing:
                ans.append(
                    Connected(
                        cls.get_sheng_ke(tg_cell1.gan, tg_cell2.gan),
                        mingpan,
                        [tg_cell1, tg_cell2])
                )
        return ans

    @classmethod
    def calc_zhi_shengke(cls, mingpan):
        sizhu = mingpan.sizhu
        ans = []
        for i in range(3):
            # 与右边一项检查(相邻)
            # 相邻两地支之间的生克关系
            dz_cell1, dz_cell2 = sizhu[i][1], sizhu[i+1][1]
            if dz_cell1.zhi.wuxing != dz_cell2.zhi.wuxing:
                ans.append(
                    Connected(
                        cls.get_sheng_ke(dz_cell1.zhi, dz_cell2.zhi),
                        mingpan,
                        [dz_cell1, dz_cell2])
                )
        return ans


class WuXingShengKe:
    """
    五行生克
    """
    _cache = {}

    def __new__(cls, source, to, name):
        if (source, to) in cls._cache:
            return cls._cache[(source, to)]
        else:
            self = super().__new__(cls)
            cls._cache[(source, to)] = self
            return self

    def __init__(self, source, to, name):
        self.source = source
        self.to = to
        self.name = name

    def __str__(self):
        return f'{self.source}{self.name}{self.to}'
